#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QIcon>
#include <QDir>
#include <QStandardPaths>
#include <QDebug>
#include <QFont>
#include <QFontDatabase>

// Include all necessary headers
#include "qmlbridge.h"
#include "devicecontroller.h"
#include "samplingmanager.h"
#include "datavisualization.h"
#include "auditlogger.h"
#include "usersession.h"
#include "permissionmanager.h"
#include "databasehandler.h"

int main(int argc, char *argv[])
{
    // Enable high DPI scaling for better display on various screens
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
    
    QApplication app(argc, argv);
    
    // Set application properties
    app.setApplicationName("BacteriaSamplerSystem");
    app.setApplicationDisplayName("浮游菌采样器控制系统");
    app.setApplicationVersion("1.0.0");
    app.setOrganizationName("BacteriaSampler");
    app.setOrganizationDomain("bacteriasampler.com");
    
    // Set application icon
    app.setWindowIcon(QIcon(":/images/bacteria_sampler_icon.png"));
    
    // Create application data directory
    QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir().mkpath(dataDir);
    
    qDebug() << "Application starting...";
    qDebug() << "Data directory:" << dataDir;
    qDebug() << "Target resolution: 1024x600";
    
    // Initialize database handler
    DatabaseHandler* dbHandler = new DatabaseHandler();
    QString dbPath = dataDir + "/bacteria_sampler.db";
    if (!dbHandler->initialize(dbPath, "bacteria_sampler_key")) {
    //if (!dbHandler->initialize(dbPath, "")) {  // 临时禁用加密
        qCritical() << "Failed to initialize database";
        return -1;
    }
    
    // Initialize audit logger
    AuditLogger* auditLogger = new AuditLogger();
    if (!auditLogger->initialize(dbPath, "bacteria_sampler_key")) {
        qCritical() << "Failed to initialize audit logger";
        return -1;
    }
    
    // Initialize user session
    UserSession* userSession = new UserSession();
    
    // Initialize permission manager
    PermissionManager* permissionManager = new PermissionManager();
    
    // Initialize device controller
    DeviceController* deviceController = new DeviceController();
    deviceController->setAuditLogger(auditLogger);
    
    // Initialize sampling manager
    SamplingManager* samplingManager = new SamplingManager();
    if (!samplingManager->initialize(deviceController, auditLogger)) {
        qCritical() << "Failed to initialize sampling manager";
        return -1;
    }
    
    qDebug() << "SamplingManager initialization completed, proceeding to DataVisualization...";
    
    // Initialize data visualization
    qDebug() << "Creating DataVisualization...";
    DataVisualization* dataVisualization = nullptr;
    try {
        dataVisualization = new DataVisualization();
        qDebug() << "DataVisualization object created successfully";
        
        qDebug() << "Initializing DataVisualization...";
        if (!dataVisualization->initialize(deviceController, samplingManager, auditLogger)) {
            qCritical() << "Failed to initialize data visualization";
            return -1;
        }
        qDebug() << "DataVisualization initialized successfully";
    } catch (const std::exception& e) {
        qCritical() << "Exception during DataVisualization creation/initialization:" << e.what();
        return -1;
    } catch (...) {
        qCritical() << "Unknown exception during DataVisualization creation/initialization";
        return -1;
    }
    
    qDebug() << "Creating QML engine...";
    
    // Create QML engine
    QQmlApplicationEngine engine;
    
    qDebug() << "Creating QML bridge...";
    
    // Initialize QML bridge
    QmlBridge* qmlBridge = new QmlBridge();
    
    qDebug() << "Setting QML bridge properties...";
    qmlBridge->setDeviceController(deviceController);
    qmlBridge->setSamplingManager(samplingManager);
    qmlBridge->setAuditLogger(auditLogger);
    qmlBridge->setUserSession(userSession);
    qmlBridge->setPermissionManager(permissionManager);
    
    qDebug() << "Setting QML context properties...";
    // Set context properties BEFORE initializing QML bridge
    engine.rootContext()->setContextProperty("qmlBridge", qmlBridge);
    engine.rootContext()->setContextProperty("deviceController", deviceController);
    engine.rootContext()->setContextProperty("samplingManager", samplingManager);
    engine.rootContext()->setContextProperty("dataVisualization", dataVisualization);
    engine.rootContext()->setContextProperty("auditLogger", auditLogger);
    engine.rootContext()->setContextProperty("userSession", userSession);
    engine.rootContext()->setContextProperty("permissionManager", permissionManager);
    
    qDebug() << "Initializing QML bridge...";
    if (!qmlBridge->initialize(&engine)) {
        qCritical() << "Failed to initialize QML bridge";
        return -1;
    }
    qDebug() << "QML bridge initialized successfully";
    
    // Note: We don't need to register QML types since we're using context properties
    // The objects are already available in QML through context properties
    
    // Load main QML file
    const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
    qDebug() << "Attempting to load QML file:" << url;
    
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url, &engine](QObject *obj, const QUrl &objUrl) {
        qDebug() << "QML object creation callback - obj:" << obj << "url:" << objUrl;
        if (!obj && url == objUrl) {
            qCritical() << "Failed to load main QML file:" << url;
            qCritical() << "QML engine errors:" << engine.rootObjects().isEmpty();
            QCoreApplication::exit(-1);
        } else if (obj) {
            qDebug() << "QML file loaded successfully, object created:" << obj;
        }
    }, Qt::QueuedConnection);
    
    // Check if QML file exists in resources
    QFile qmlFile(":/qml/main.qml");
    if (!qmlFile.exists()) {
        qCritical() << "QML file does not exist in resources!";
        qCritical() << "Available resources:";
        QDir resourceDir(":/");
        QStringList entries = resourceDir.entryList();
        for (const QString& entry : entries) {
            qDebug() << "  " << entry;
        }
        QDir qmlResourceDir(":/qml");
        QStringList qmlEntries = qmlResourceDir.entryList();
        qDebug() << "QML resources:";
        for (const QString& entry : qmlEntries) {
            qDebug() << "  " << entry;
        }
    } else {
        qDebug() << "QML file found in resources";
    }
    
    engine.load(url);
    
    // Check if any root objects were created
    QList<QObject*> rootObjects = engine.rootObjects();
    qDebug() << "Number of root objects created:" << rootObjects.size();
    if (rootObjects.isEmpty()) {
        qCritical() << "No root objects created - QML loading failed!";
        
        // Try to get more detailed error information
        QStringList importPaths = engine.importPathList();
        qDebug() << "QML import paths:";
        for (const QString& path : importPaths) {
            qDebug() << "  " << path;
        }
        
        return -1;
    } else {
        for (QObject* obj : rootObjects) {
            qDebug() << "Root object:" << obj << "type:" << obj->metaObject()->className();
        }
    }
    
    // Initialize device on startup
    qDebug() << "Initializing device...";
    if (!deviceController->initializeDevice()) {
        qWarning() << "Device initialization failed:" << deviceController->getLastError();
        // Continue anyway for testing purposes
    } else {
        qDebug() << "Device initialized successfully";
    }
    
    // Log application startup
    AuditLogger::AuditRecord startupRecord;
    startupRecord.timestamp = QDateTime::currentDateTime();
    startupRecord.userId = "system";
    startupRecord.action = AuditLogger::System;
    startupRecord.tableName = "application";
    startupRecord.recordId = "startup";
    startupRecord.oldValue = "";
    startupRecord.newValue = "Application started";
    startupRecord.description = "Bacteria Sampler System application started";
    auditLogger->logEvent(startupRecord);
    
    qDebug() << "Application initialized successfully";
    qDebug() << "Starting main event loop...";
    
    // Start the application event loop
    int result = app.exec();
    
    // Cleanup on exit
    qDebug() << "Application shutting down...";
    
    // Log application shutdown
    AuditLogger::AuditRecord shutdownRecord;
    shutdownRecord.timestamp = QDateTime::currentDateTime();
    shutdownRecord.userId = "system";
    shutdownRecord.action = AuditLogger::System;
    shutdownRecord.tableName = "application";
    shutdownRecord.recordId = "shutdown";
    shutdownRecord.oldValue = "";
    shutdownRecord.newValue = "Application shutdown";
    shutdownRecord.description = "Bacteria Sampler System application shutdown";
    auditLogger->logEvent(shutdownRecord);
    
    // Shutdown device
    deviceController->shutdownDevice();
    
    // Cleanup objects
    delete qmlBridge;
    delete dataVisualization;
    delete samplingManager;
    delete deviceController;
    delete permissionManager;
    delete userSession;
    delete auditLogger;
    delete dbHandler;
    
    qDebug() << "Application shutdown complete";
    return result;
}